#include "stdafx.h"
#include "Plane.h"
#include <cmath>

//-------------------------------------------------------------------------
// constructors
//-------------------------------------------------------------------------

CPlane::CPlane()
{
	D = 0.0f;
}

//-------------------------------------------------------------------------

CPlane::CPlane(vector3f normal_, float D_)
{
	normal = normal_;
	D = D_;
}

//-------------------------------------------------------------------------
// operators
//-------------------------------------------------------------------------

bool CPlane::operator == (const CPlane pl) const
{
	return (normal.x == pl.normal.x && normal.y == pl.normal.y && 
			normal.z == pl.normal.z && D == pl.D);
}

//-------------------------------------------------------------------------
// functions
//-------------------------------------------------------------------------

void CPlane::PlaneEquation(vector3f a, vector3f b, vector3f c)
{
	normal = CrossProduct((b-a), (c-a));
	normal.Normalize();
	D = DotProduct((normal * -1.0f), a);
}

//-------------------------------------------------------------------------

void CPlane::Set(const float x_, const float y_, const float z_, 
			     const float D_)
{
	normal.x = x_;
	normal.y = y_;
	normal.z = z_;
	D = D_;
}

//-------------------------------------------------------------------------

void CPlane::Normalize()
{
	float length = normal.Length();
	if (length == 0.0f) length = 1.0f;
	float avoid_div = 1.0f / length;
	normal.x *= avoid_div;
	normal.y *= avoid_div;
	normal.z *= avoid_div;
	D *= avoid_div;
}

//-------------------------------------------------------------------------

float CPlane::PointToPlaneDistance(const vector3f p)
{
	return (DotProduct(normal, p) + D);
}

//-------------------------------------------------------------------------

bool CPlane::PointInFrontOfPlane(const vector3f p)
{
	return (PointToPlaneDistance(p) > 0.0f);
}

//-------------------------------------------------------------------------

bool CPlane::PointBehindPlane(const vector3f p)
{
	return (PointToPlaneDistance(p) < 0.0f);
}

//-------------------------------------------------------------------------

bool CPlane::PointOnPlane(const vector3f p)
{
	return (PointToPlaneDistance(p) == 0.0f);
}

//-------------------------------------------------------------------------

bool CPlane::PointInFrontOrOnPlane(const vector3f p)
{
	return (PointToPlaneDistance(p) >= 0.0f);
}

//-------------------------------------------------------------------------

bool CPlane::PointOnOrBehindPlane(const vector3f p)
{
	return (PointToPlaneDistance(p) <= 0.0f);
}

//-------------------------------------------------------------------------

float CPlane::AngleBetweenPlanes(const CPlane pl)
{
	float num = DotProduct(normal, pl.normal);
	float den = normal.Length() * pl.normal.Length();
	return acosf(num / den);
}
